#include "led.h"

/***********************************************************
*函数名：delay_ms
*函数功能：延时指定毫秒
*函数参数：int n，表示n毫秒
*函数返回值：无
*函数说明：为了避免重复定义，限当前源文件使用。
					 此函数延时不是很精确，后面用定时器代替。
************************************************************/
static void delay_ms(int n)
{
	int i = 168/4*50*n;
	while(i)
	{
		i--;
	}
}

/***********************************************************
*函数名：delay_us
*函数功能：延时指定微秒
*函数参数：int n，表示n微秒
*函数返回值：无
*函数说明：为了避免重复定义，限当前源文件使用。
					 此函数延时不是很精确，后面用定时器代替。
************************************************************/
static void delay_us(int n)
{
	int i = 168*n;
	while(i)
	{
		i--;
	}
}

/***********************************************************
*函数名：Led_Init
*函数功能：对led灯连接的GPIO口进行初始化配置
*函数参数：无
*函数返回值：无
*函数说明：
						LED1——PC4——通用输出推挽模式，2MHz，无上拉/下拉
						LED2——PC5——通用输出推挽模式，2MHz，无上拉/下拉
						LED3——PC6——通用输出推挽模式，2MHz，无上拉/下拉
						LED4——PC7——通用输出推挽模式，2MHz，无上拉/下拉
************************************************************/
void Led_Init(void)
{
	/*把GPIOC控制器的时钟打开*/
	RCC->AHB1ENR |= (1<<2);//打开GPIOC时钟

	/*用GPIO控制器配置GPIO口*/
	//模式寄存器——通用输出模式 01
	GPIOC->MODER &= ~(3<<4*2);
	GPIOC->MODER |= (1<<4*2);
	GPIOC->MODER &= ~(3<<5*2);
	GPIOC->MODER |= (1<<5*2);
	GPIOC->MODER &= ~(3<<6*2);
	GPIOC->MODER |= (1<<6*2);
	GPIOC->MODER &= ~(3<<7*2);
	GPIOC->MODER |= (1<<7*2);
	//可以替换为
	//GPIOC->MODER &= ~(3<<8 | 3<<10 | 3<<12 | 3<<14);
	//GPIOC->MODER |= (1<<8 | 1<<10 | 1<<12 | 1<<14);

	//输出类型寄存器——推挽 0
	GPIOC->OTYPER &= ~(1<<4);
	GPIOC->OTYPER &= ~(1<<5);
	GPIOC->OTYPER &= ~(1<<6);
	GPIOC->OTYPER &= ~(1<<7);
	//可以替换为
	//GPIOC->OTYPER &= ~(1<<4 | 1<<5 | 1<<6 | 1<<7);

	//输出速度寄存器——2MHz 00
	GPIOC->OSPEEDR &= ~(3<<4*2);
	GPIOC->OSPEEDR &= ~(3<<5*2);
	GPIOC->OSPEEDR &= ~(3<<6*2);
	GPIOC->OSPEEDR &= ~(3<<7*2);
	//可以替换为
	//GPIOC->OSPEEDR &= ~(3<<8 | 3<<10 | 3<<12 | 3<<14);

	//上拉/下拉寄存器——无上下拉 00
	GPIOC->PUPDR &= ~(3<<4*2);
	GPIOC->PUPDR &= ~(3<<5*2);
	GPIOC->PUPDR &= ~(3<<6*2);
	GPIOC->PUPDR &= ~(3<<7*2);
	//可以替换为
	//GPIOC->PUPDR &= ~(3<<8 | 3<<10 | 3<<12 | 3<<14);

	/*关闭LED灯*/
	//输出数据寄存器的相应位置1
	GPIOC->ODR |= (1<<4);//关闭LED1
	GPIOC->ODR |= (1<<5);//关闭LED2
	GPIOC->ODR |= (1<<6);//关闭LED3
	GPIOC->ODR |= (1<<7);//关闭LED4
	//可以替换为
	//GPIOC->ODR |= (1<<4 | 1<<5 | 1<<6 | 1<<7);

}

/***********************************************************
*函数名：Led_All_On
*函数功能：打开所有led灯
*函数参数：无
*函数返回值：无
*函数说明：
************************************************************/
void Led_All_On(void)
{
	LED1_ON;
	LED2_ON;
	LED3_ON;
	LED4_ON;
}

/***********************************************************
*函数名：Led_All_Off
*函数功能：关闭所有led灯
*函数参数：无
*函数返回值：无
*函数说明：
************************************************************/
void Led_All_Off(void)
{
	LED1_OFF;
	LED2_OFF;
	LED3_OFF;
	LED4_OFF;
}

/***********************************************************
*函数名：Led_On
*函数功能：打开指定的某一个led灯
*函数参数：char n，表示第n个灯
*函数返回值：无
*函数说明：
************************************************************/
void Led_On(char n)
{
	switch(n)
	{
		case 1:LED1_ON;break;
		case 2:LED2_ON;break;
		case 3:LED3_ON;break;
		case 4:LED4_ON;break;
	}
}

/***********************************************************
*函数名：Led_Off
*函数功能：关闭指定的某一个led灯
*函数参数：char n，表示第n个灯
*函数返回值：无
*函数说明：
************************************************************/
void Led_Off(char n)
{
	switch(n)
	{
		case 1:LED1_OFF;break;
		case 2:LED2_OFF;break;
		case 3:LED3_OFF;break;
		case 4:LED4_OFF;break;
	}
}


/***********************************************************
*函数名：Led_Flash
*函数功能：让指定的led灯闪烁
*函数参数：char n，表示第n个灯
*函数返回值：无
*函数说明：
************************************************************/
void Led_Flash(char n)
{
	switch(n)
	{
		case 1:LED1_OVERTURN;break;
		case 2:LED2_OVERTURN;break;
		case 3:LED3_OVERTURN;break;
		case 4:LED4_OVERTURN;break;
	}
	delay_ms(500);
}


/***********************************************************
*函数名：Led_Control
*函数功能：打开或关闭指定的某一个led灯
*函数参数：char n，表示第n个灯	char c，表示开灯(1)或关灯(0)
*函数返回值：无
*函数说明：
************************************************************/
void Led_Control(char n,char c)
{
	if(c == 1)
		Led_On(n);
	else if(c == 0)
		Led_Off(n);
}


/***********************************************************
*函数名：Led_Overturn
*函数功能：翻转指定的led灯
*函数参数：u8 n，表示第n个led灯
*函数返回值：无
*函数说明：
************************************************************/
void Led_Overturn(uint8_t n)
{
	switch(n)
	{
		case 1:LED1_OVERTURN;break;
		case 2:LED2_OVERTURN;break;
		case 3:LED3_OVERTURN;break;
		case 4:LED4_OVERTURN;break;
	}
}


/***********************************************************
*函数名：Led_All_Flash
*函数功能：所有led灯一起闪烁
*函数参数：无
*函数返回值：无
*函数说明：
************************************************************/
void Led_All_Flash(void)
{
	Led_All_On();
	delay_ms(500);
	Led_All_Off();
	delay_ms(500);
}

/***********************************************************
*函数名：Led_Water
*函数功能：流水灯
*函数参数：无
*函数返回值：无
*函数说明：LED1、LED2、LED3、LED4依次亮，依次灭，不断循环
************************************************************/
void Led_Water(void)
{
	u8 a,b = 1;
	while(1)
	{
		for(a = 1;a <= 4;a++)
		{
			Led_Control(a,b);//b为1表示开灯，为0表示关灯
			delay_ms(50);
		}
		b = b^1;//将b取反
	}
}


/***********************************************************
*函数名：Led_Water_Speed
*函数功能：控制流水灯的速度
*函数参数：u32 speed，表示速度
*函数返回值：无
*函数说明：
************************************************************/
void Led_Water_Speed(u32 speed)
{
	static u8 i = 1;
	static u32 acc = 0;//累积值
	static u8 flag = 1;

	acc++;
	if(flag == 1)
	{
		if(acc >= 210000.0/speed)
		{
			Led_On(i);
			acc = 0;
			i++;
			if(i > 4)
			{
				i = 1;
				flag = 0;
			}
		}
	}
	else
	{
		if(acc >= 210000.0/speed)
		{
			Led_Off(i);
			acc = 0;
			i++;
			if(i > 4)
			{
				i = 1;
				flag = 1;
			}
		}
	}
}


/***********************************************************
*函数名：Led_Water_Control
*函数功能：用按键控制流水灯
*函数参数：无
*函数返回值：无
*函数说明：
					KEY1——增速
					KEY3——减速
					KEY2——开灯
					KEY4——关灯
************************************************************/
void Led_Water_Control(void)
{
	static s32 speed = 100;
	u8 key = 0xff;
	static u8 flag = 1;//开关灯标志位，1表示开灯，0表示关灯

	key = keyscan();
	switch(key)
	{
		case 1:
		{
			if(flag)	speed = speed + 20;//if(flag)的作用：防止在关灯时仍然能改变速度
			if(speed > 1000)	speed = 1000;
			break;
		}
		case 2:flag = 1;break;
		case 3:
		{
			if(flag)	speed = speed - 20;//if(flag)的作用：防止在关灯时仍然能改变速度
			if(speed < 5)	speed = 5;
			break;
		}
		case 4:flag = 0;break;
	}

	if(flag)
		Led_Water_Speed(speed);
	else
		Led_All_Off();
}


/***********************************************************
*函数名：Led_Horse
*函数功能：跑马灯
*函数参数：无
*函数返回值：无
*函数说明：LED1亮、灭，LED2亮、灭，……，不断循环
************************************************************/
void Led_Horse(void)
{
	u8 a = 1;
	while(1)
	{
		Led_On(a);
		delay_ms(80);
		Led_Off(a);
		if(a == 4)	a = 1;
		else				a++;
	}
}

/***********************************************************
*函数名：Led_Horse_Speed
*函数功能：控制跑马灯的速度
*函数参数：u32 speed，表示速度
*函数返回值：无
*函数说明：
************************************************************/
void Led_Horse_Speed(u32 speed)
{
	static u32 count = 0;
	static u8 n = 1;

	count++;
	Led_All_Off();
	Led_On(n);
	if(count >= 2100000.0/speed)
	{
		count = 0;
		n++;
		if(n > 4)	n = 1;
	}
}


/***********************************************************
*函数名：Led_Bright
*函数功能：控制指定LED灯的亮度
*函数参数：char n,表示第n个LED灯
					 u32 ontime,表示开灯时长(ms)
					 u32 T,表示周期(ms)
*函数返回值：无
*函数说明：占空比 = ontime/T 越大，亮度越高
************************************************************/
void Led_Bright(char n,u32 ontime,u32 T)
{
	Led_On(n);
	delay_us(ontime);
	Led_Off(n);
	delay_us(T-ontime);
}


/***********************************************************
*函数名：Led_Breath
*函数功能：呼吸灯（LED1）
*函数参数：无
*函数返回值：无
*函数说明：逐渐变亮，再逐渐变暗
************************************************************/
void Led_Breath(void)
{
	u32 ton = 0,toff = 1000;

	while(toff)
	{
		LED1_ON;
		delay_us(ton);
		LED1_OFF;
		delay_us(toff);
		ton++;
		toff--;
	}
	delay_ms(10);
	while(ton)
	{
		LED1_ON;
		delay_us(ton);
		LED1_OFF;
		delay_us(toff);
		ton--;
		toff++;
	}
}

/***********************************************************
*函数名：Led_Key_Control
*函数功能：用按键控制LED灯的亮灭
*函数参数：无
*函数返回值：无
*函数说明：
					KEY1——LED1
					KEY2——LED2
					KEY3——LED3
					KEY4——LED4
************************************************************/
void Led_Key_Control(void)
{
	u8 key = 0xff;
	key = keyscan();
	switch(key)
	{
		case 1:LED1_OVERTURN;break;
		case 2:LED2_OVERTURN;break;
		case 3:LED3_OVERTURN;break;
		case 4:LED4_OVERTURN;break;
	}
}


